package TimeLine;

import java.util.Iterator;
import java.util.Timer;
import java.util.Vector;
/**
 * Class TimeLine
 * Classe de lancement automatique et périodique de methodes.
 * TimeLine utilise des timers
 */
public class TimeLine {
	/**
	 * Ratio de division du temps
	 */
	private int ratio = 1;
	/**
	 *  Liste des actions
	 */
	private Vector<Action> actions;
	/**
	 * Liste des actions en cours d'execution
	 */
	private Vector<Action> launched;
	/**
	 * Timer pour lancer les actions
	 */
	private Timer time;
	/**
	 * Etat du timeLine (Demarer ou non)
	 */
	boolean started = false;
	/**
	 * Constructeur
	 */
	public TimeLine () {
		this.time = new Timer();
		this.actions = new Vector<Action>();
		this.launched = new Vector<Action>();
	};
	/**
	 * Modifie le ratio et relance les actions si le timer est démarer
	 * @param newVar la nouvelle valeur du ratio
	 */
	public void setRatio ( int newVar ) {
		if(newVar == 0){
			newVar = 1;
		}
		Iterator it = this.actions.iterator();
		Action a;
		while(it.hasNext()){
			a = (Action)it.next();
			if(newVar > a.getDelay()){
				newVar = this.ratio;
			}
		}
		if(this.ratio != newVar){
			this.ratio = newVar;
			if (this.actions.size()>0 && this.started) {
				this.cancelActions();
				this.scheduleActions();
			}
		}
	}
	/**
	 * Ascesseur de la liste des Actions
	 * @return la liste des Actions
	 */
	public Vector<Action> getActions() {
		return this.actions;
	}
	/**
	 * Ascesseur du ratio
	 * @return la valeur du ratio
	 */
	public int getRatio ( ) {
		return this.ratio;
	}
	/**
	 * Annule toutes les action
	 */
	private void cancelActions() {
		Iterator it = this.launched.iterator();
		while (it.hasNext()) {
			((Action)it.next()).cancel();
		}
		this.launched.removeAllElements();
	}
	/**
	 * Programme une action
	 * @param a L'action a programmer
	 */
	private void scheduleAction(Action a) {
		if(ratio > 0){
			this.time.schedule(a,0, a.getDelay()/ratio);
		}
	}
    /**
     * Programmes toutes les actions
     */
    private void scheduleActions() {
        Iterator it = this.actions.iterator();
        Action tmp;
        while (it.hasNext()) {
            tmp = ((Action)it.next()).clone();
	    this.launched.add(tmp);
            this.scheduleAction(tmp);
        }
    }
    /**
     * Methods d'ajout d'une methode a apeller automatiquement
     * @param        delay Delay entre deux lancement de la tache en miliseconde
     * @param        obj Objet sur le quel sera apeller la methode
     * @param        method Nom de la methode a apeller
     */
    public void addMethodCall( int delay, Object obj, String method ) {
        Action a = new Action(obj,method,delay);
        this.actions.add(a);
	if(this.started){
		this.scheduleAction(a);
	}
    }


    /**
     * Liste toutes les methodes qui sont apeller automatiquement
     * @return       String
     */
    @Override
    public String toString(  ) {
        String liste = new String();
        Iterator it = actions.iterator();
        while (it.hasNext()) {
            Action a = (Action)(it.next());
            liste += a.getObject().getClass().toString()+" ";
            liste += a.getMethod()+" ";
        }
        return liste;
    }


    /**
     * Supprimer une methode
     * @param        obj Objet de la demande à supprpimer
     * @param        method Methode de la demande a supprimer
     */
    public void removeMethodCall( Object obj, String method ) {
        Action b = new Action(obj,method,0);
        int tmp = this.actions.indexOf(b);
        if (tmp!=-1) {
            this.actions.get(tmp).cancel();
            this.actions.remove(tmp);
        }
    }

    /**
     * Lance le TimeLine
     */
    public void start(){
	    this.started = true;
	    this.scheduleActions();
    }

    /**
     * Stop le TimeLine
     */
    public void stop(){
	    this.started = false;
	    this.cancelActions();
    }


    /**
     * Pour savoir si le timer est lancer ou non
     * @return l'êtat du timer
     */
    public boolean isStarted(){
	    return this.started;
    }


}
